﻿/*
 * Created by SharpDevelop.
 * User: Admin
 * Date: 13.10.2010
 * Time: 8:49
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace HK.FiscalRegistrar
{
	/// <summary>
	/// Класс для работы с фискальным регистратором
	/// </summary>
	public static class FiscalRegistrar
	{
		#region Члены класса
		public static string str = ""; // Для записи результатов выполнения методов
		
		private static DataTable checkFreeDataTable; // Таблица для данных не фискального чека
		private static DataTable checkDataTable; // Таблица для данных фискального чека
		
		private static byte[] opName; // Имя опратора
		/// <summary>
		/// Имя оператора
		/// </summary>
		public static string OpName {
			get { return opName.ToString(); }
			set {
				opName = GetOEMDOSStr(value);
			}
		}
		
		private static string psw; // Пароль
		/// <summary>
		/// Пароль на доступ к ФР
		/// </summary>
		public static string Psw {
			get { return psw; }
			set { psw = value; }
		}
		
		private static string devName; // Имя порта
		/// <summary>
		/// Имя порта
		/// </summary>
		public static string DevName {
			get { return devName; }
			set { devName = value; }
		}
		
		private static int flagOem; // Опции для подключения
		/// <summary>
		/// Опции подключения
		/// </summary>
		public static int FlagOem {
			get { return flagOem; }
			set { flagOem = value; }
		}
		#endregion
		
		#region Методы класса
		#region Функции импортированниые из DLL
		/// <summary>
		/// Открыть соединение
		/// </summary>
		/// <param name="OpName">Имя оператора</param>
		/// <param name="Psw">Пароль</param>
		/// <param name="DevName">Название порта ("COM1, COM2, COM3, COM4")</param>
		/// <param name="FlagOem"></param>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int OpenDLL(byte[] OpName, string Psw, string DevName, int FlagOem);
		
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int CloseDLL();
		
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int StartSeans();
		
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int ShiftOpen(byte[] Buf);
		
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int ShiftClose();
			
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int OpenFDoc();
		
		/// <summary>
		/// Печать произвольной информации
		/// </summary>
		/// <param name="Information">Буфер с текстом для вывода на принтер</param>
		/// <param name="Len">Размер буфера в байтах</param>
		/// <example><code>PrintFDoc("123", 3);</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int PrintFDoc(byte[] Information, long Len);
		
		/// <summary>
		/// Печать произвольной информации в OEM кодировке
		/// </summary>
		/// <param name="Information">Буфер с текстом для вывода на принтер</param>
		/// <param name="Len">Размер буфера в байтах</param>
		/// <example><code>PrintOEMDoc("123", 3);</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int PrintOEMDoc(string Information, long Len);
		
		/// <summary>
		/// Печать произвольной информации в OEM кодировке с завершающим CRLF
		/// </summary>
		/// <param name="Information">Буфер с текстом для вывода на принтер</param>
		/// <param name="Len">Размер буфера в байтах</param>
		/// <example><code>PrintOEMCRLFDoc("123", 3);</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int PrintOEMCRLFDoc(string Information, long Len);
		
		/// <summary>
		/// Перевод ФР в режим принтера, отрезка бумаги
		/// </summary>
		/// <example><code>FreeDocCut();</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int FreeDocCut();
		
		/// <summary>
		/// Перевод ФР в режим принтера, отрезка бумаги с заданным числом строк перед отрезкой
		/// </summary>
		/// <example><code>FreeDocCutPlus(10);</code> - отрезка после десяти строк</example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int FreeDocCutPlus(byte count);
		
		/// <summary>
		/// Изменение сферы применения ККМ, установленной при фискализации/перерегистрации
		/// </summary>
		/// <param name="ServiceType">Тип сферы</param>
		/// <param name="OperatorPosition">должность оператора</param>
		/// <example><code>ChangeService(2, "Администратор");</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int ChangeService(byte ServiceType, string OperatorPosition);
		
		/// <summary>
		/// Получение серийного номера ККМ
		/// </summary>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int GetSerialNum();
		
		/// <summary>
		/// Получение фискальных номеров
		/// </summary>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int GetFiscalNums();
		
		/// <summary>
		/// Выдача в регистратор команды "запрос текущих номеров документов"
		/// </summary>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int GetNumbers();
		
		/// <summary>
		/// Выдача в регистратор команды "открытие денежного ящика"
		/// </summary>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int CashDriverOpen();
		
		/// <summary>
		/// Запись номера версии по указателю DllVer
		/// </summary>
		/// <param name="DllVer">адрес строки, в которую будет записана версия библиотеки</param>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int GetDllVer(string DllVer);
		
		/// <summary>
		/// Установка таймаутов COM-порта в миллисекундах
		/// </summary>
		/// <param name="WaitRXTime">таймаут передачи</param>
		/// <param name="WaitTXTime">таймаут приема</param>
		/// <code><example>SetCommTimeoutMs(1000, 1000)</example> - установить таймауты равными одной секунде</code>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int SetCommTimeoutMs(int WaitRXTime, int WaitTXTime);
		
		/// <summary>
		/// Выдача в регистратор комманды "программирование пароля на связь"
		/// </summary>
		/// <param name="Psw">парол связи</param>
		/// <code><example>SetPassword("AERF")</example> - установить пароль "AERF"</code>
		/// <returns></returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int SetPassword(string Psw);
		
		/// <summary>
		/// Считывание одного из 6-ти байтов статуса ККМ по его номеру
		/// </summary>
		/// <param name="Num">номер байта статуса. От 1 до 6</param>
		/// <example><code>GetStatusNum(2)</code> - считать из второго байта статус ККМ</example>
		/// <remarks>Статус ККМ предварительно должен быть запрошен функцией GetStatus() или GetStatusPlus()</remarks>
		/// <returns>Байт статуса</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int GetStatusNum(int Num);
		
		/// <summary>
		/// Проверка одного из 8 битов одного из 6-ти байтов статуса ККМ
		/// </summary>
		/// <param name="Num">Номер байта статуса. От 1 до 6</param>
		/// <param name="BitNum">Номер проверяемого бита. 0 до 7</param>
		/// <example><code>Check(2, 1)</code> - Проверить первый бит второго байта статуса</example>
		/// <remarks>Статус ККМ предварительно должен быть запрошен функцией GetStatus() или GetStatusPlus()</remarks>
		/// <returns>байт статуса</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int CheckStatusNum(int Num, int BitNum);
		
		/// <summary>
		/// Выдача в регистратор команды "информация о свободных ресурсах"
		/// </summary>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		public static extern int GetResource();
		
		/// <summary>
		/// 1. Выдача в регистратор комнды "начать формирование документа на чеке"
		/// 2. Запоминание типа документа - чек
		/// </summary>
		/// <param name="DocType">тип документа</param>
		/// <param name="Copies">число копий</param>
		/// <param name="TableNo">номер столика, комнаты, ТРК</param>
		/// <param name="PlaceNo">номер места</param>
		/// <param name="AccountNo">номер счета</param>
		/// <example><code>StartReceipt(0, 1, "", "", "")</code></example>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int StartReceipt(byte DocType, byte Copies, string TableNo, string PlaceNo, string AccountNo);
		
		/// <summary>
		/// 1. Выдача в регистратор комнды "начать формирование документа на чеке"
		/// 2. Печать произвольного текста на чеке
		/// 3. Запоминание типа документа - чек
		/// </summary>
		/// <param name="DocType">тип документа</param>
		/// <param name="Copies">число копий</param>
		/// <param name="TableNo">номер столика, комнаты, ТРК</param>
		/// <param name="PlaceNo">номер места</param>
		/// <param name="AccountNo">номер счета</param>
		/// <param name="FreeField">произвольный текст</param>
		/// <example><code>StartReceiptPlus(0, 1, "", "", "", "Произв строка 1| Произв строка 2")</code></example>
		/// <remarks>для выполнения принудительного перевода строки используется символ 7Ch</remarks>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int StartReceiptPlus(byte DocType, byte Copies, string TableNo, string PlaceNo, string AccountNo, string FreeField);
		
		/// <summary>
		/// Выдача в регистратор команды "продажа на чеке"
		/// </summary>
		/// <param name="WareName">наименование товара / услуги</param>
		/// <param name="WareCode">артикул товара / код товара</param>
		/// <param name="Measure">еденицы измерения</param>
		/// <param name="SecID">наименование секции</param>
		/// <param name="Price">цена в копеках</param>
		/// <param name="Count">колличество в штуках / вес в миллиграмах</param>
		/// <param name="WareType">тип товара</param>
		/// <example><code>ItemReceipt("СИГАРЕТЫ SALEM", "012345", "ШТ", "БАКАЛЕЯ", 4950, 2000, 1)</code></example>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int ItemReceipt(byte[] WareName, byte[] WareCode, byte[] Measure, byte[] SecID, int Price, int Count, byte WareType);
		
		/// <summary>
		/// Выдача в регистратор командв "подитог на чеке"
		/// </summary>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int SubTotalReceipt();
		
		/// <summary>
		/// 1. Выдача в регистратор команды "итог на чеке"
		/// 2. Завершение оформления документа
		/// </summary>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int TotalReceipt();
		
		/// <summary>
		/// Выдача в регистратор команды "расчет на чеке"
		/// </summary>
		/// <param name="PayType">Вид оплаты</param>
		/// <param name="TenderSum">сумма в копейках, внесенная покупателем</param>
		/// <param name="CardName">название платежной карты</param>
		/// <param name="FreeField">Произвольный текст</param> 
		/// <example><code>TenderReceiptPlus(0, 9900, "", "Произвольная строка1 | Произвольная строка 2")</code></example>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int TenderReceiptPlus(byte PayType, int TenderSum, byte[] CardName, byte[] FreeField);
		
		/// <summary>
		/// Выдача в регистратор команды "расчет на чеке"
		/// </summary>
		/// <param name="PayType">Вид оплаты</param>
		/// <param name="TenderSum">сумма в копейках, внесенная покупателем</param>
		/// <param name="CardName">название платежной карты</param>
		/// <example><code>TenderReceipt(0, 9900, "")</code></example>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int TenderReceipt(byte PayType, int TenderSum, string CardName);
		
		/// <summary>
		/// Выдача в регистратор команды "закрытие документа"
		/// </summary>
		/// <returns>код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int CloseReceipt();
		
		/// <summary>
		/// Выдача в регистратор команды "Аннулирование документа на чеке"
		/// </summary>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int CancelReceipt();
		
		/// <summary>
		/// Назначить налог
		/// </summary>
		/// <param name="TaxType">Индекс налога</param>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int TaxReceipt(byte TaxType);
		
		/// <summary>
		/// Изменяет формат выводимых символов
		/// </summary>
		/// <param name="Font">Маска шрифта в соответствии с командой ESC
		/// 	<para>  0 - Выбор шрифта (A или B)</para>
		/// 	<para>  1-2 - не определено</para>
		/// 	<para>  3 - жирность</para>
		/// 	<para>  4 - печатать символы удвоенной высоты</para>
		/// 	<para>  5 - печатать символы удвоенной ширины</para>
		/// 	<para>  6 - не определено</para>
		/// 	<para>  7 - символы с подчеркиванием</para>
		/// </param>
		/// <returns>Код ошибки</returns>
		/// <example>
		/// 	<code>
		/// 		<para>OpenFDoc();</para>
		/// 		<para>FontSelectFDoc(0x21);</para>
		/// 		<para>PrintOEMCRLFFDoc("Двойной ширины");</para>
		/// 		<para>FontSelectFDoc(0x11);</para>
		/// 		<para>PrintOEMCRLFFDoc("Двойной высоты");</para>
		/// 		<para>FontSelectFDoc(0x01);</para>
		/// 		<para>PrintOEMCRLFFDoc("Нормальный");</para>
		/// 		<para>CloseFDoc();</para>
		/// 	</code>
		/// </example>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int FontSelectFDoc(byte Font);
		
		/// <summary>
		/// Выдача в регистратор команды "Программирование параметров налоговой ставки"
		/// </summary>
		/// <param name="TIndex">Индекс налоговой ставки</param>
		/// <param name="TType">Тип ставки(резерв)</param>
		/// <param name="TName">Название</param>
		/// <param name="TValue">Процент</param>
		/// <param name="TMin">Минимальное значение(резерв)</param>
		/// <example><code>  SetTaxes(0, 0, "НДС", "18", 0)</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int SetTaxes(byte TIndex, byte TType, byte[] TName, byte[] TValue, byte[] TMin);
		
		/// <summary>
		/// Выдача в регистратор команды "Чтение параметров налоговой ставки"
		/// </summary>
		/// <param name="TIndex">Индекс налоговой ставки</param>
		/// <example><code>  GetTaxes(0)</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int GetTaxes(byte TIndex);
		
		/// <summary>
		/// Выдача в регистратор команды "внесение"
		/// </summary>
		/// <param name="ToCash">Сумма внесенная в кассу(копейки)</param>
		/// <example><code>  ToCash(12300)</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int ToCash(int Sum);
		
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int GetErrorMessage(out string Buf);
		
		/// <summary>
		/// Отчет по закрытиям смен в диапазоне номеров смен
		/// </summary>
		/// <param name="ReportType">Тип отчета
		/// 	<para>  06 - Полный</para>
		/// 	<para>  07 - Краткий</para>
		/// </param>
		/// <param name="StartNo">Номер начальной смены</param>
		/// <param name="EndNo">Номер конечной смены</param>
		/// <example><code>  EKLShiftsNumReport(06, 123, 321) - Напечатать полный отчет с 123 закрытия по 321</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int EKLShiftsNumReport(int ReportType, int StartNo, int EndNo);
		
		/// <summary>
		/// Установить параметры денежного ящика
		/// </summary>
		/// <param name="OnTime">Время On в импульсах х 10ms</param>
		/// <param name="OffTime">Время Off в импульсах х 10ms</param>
		/// <param name="PramDoc1">Параметр 1</param>
		/// <example><code>  SetDrawerParam(5, 5, 0) - установить на 50ms включение и 50ms выключение</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int SetDrawerPram(byte OnTime, byte OffTime, long PramDoc1);
		
		/// <summary>
		/// Печатает Х-отчет
		/// </summary>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int XReport();
		
		/// <summary>
		/// Печать контрольной ленты за смену
		/// </summary>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int EJPrint();
		
		/// <summary>
		/// Печать документов из СКЛ в заданном диапазоне номеров
		/// </summary>
		/// <param name="StartNum">Начальный номер</param>
		/// <param name="EndNum">Конечный номер</param>
		/// <example><code>  EJNoReport(1, 10)</code></example>
		/// <returns>Код ошибки</returns>
		[DllImport("Azimuth.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.StdCall)]
		private static extern int EJNoReport(int StartNum, int EndNum);
		#endregion
		
		#region Методы обертки для работы с функциями из DLL
		/// <summary>
		/// Открыть соединение
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static int FROpenDLL()
		{
			int i = OpenDLL(opName, Psw, DevName, flagOem);
			str += "OpenDLL " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Закрыть соединение
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static int FRCloseDLL()
		{
			int i = CloseDLL();
			str += "CloseDLL " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Открыть сеанс
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static int FRStartSeans()
		{
			int i = StartSeans();
			str += "StartSeans " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// 1.Выдача в регистратор команда Открыть смену; 2.Печать произвольного текста на чеке
		/// </summary>
		/// <param name="Buf">Производьный текст</param>
		/// <returns>Код ошибки</returns>
		public static int FRShiftOpen(string buf)
		{
			int i = ShiftOpen(
				GetOEMDOSStr(buf)
			);
			str += "ShiftOpen " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Закрывает смену
		/// </summary>
		/// <returns></returns>
		public static int FRShiftClose()
		{
			int i = ShiftClose();
			str += "ShiftClose " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Перевод фискального регистратора в режим принтера
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static int FROpenFDoc()
		{
			int i = OpenFDoc();
			str += "OpenFDoc " + i + "\n";
			return i;
		}
		
		public static int FRPrintFDoc(string str)
		{
			byte[] dosStr = GetOEMDOSStr(str);
			int i = PrintFDoc(dosStr, dosStr.Length);
			str += "PrintFDoc " + i + "\n";
			return i;
		}
		/// <summary>
		/// Печать произвольной информации в OEM кодировке с завершающим CRLF
		/// </summary>
		/// <param name="Information">Буфер с текстом для вывода на принтер</param>
		/// <param name="Len">Размер буфера в байтах</param>
		/// <example><code> PrintOEMCRLFDoc("123", 3);</code></example>
		/// <returns>Код ошибки</returns>
		public static int FRPrintOEMCRLFDoc(string information, long len)
		{
			Console.WriteLine(information);
            int i = PrintOEMCRLFDoc(information, information.Length);
            str += "PrintOEMCRLFDoc " + i + "\n";
            return i;
		}
		
		/// <summary>
		/// Перевод ФР в режим принтера, отрезка бумаги с заданным числом строк перед отрезкой
		/// </summary>
		/// <example><code>FreeDocCutPlus(10);</code> - отрезка после десяти строк</example>
		/// <returns>Код ошибки</returns>
		public static int FRFreeDocCutPlus(byte count)
		{
			Console.WriteLine("-----------------------------------------");
			int i = FreeDocCutPlus(count);
			str += "FreeDocCutPlus " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// 1. Выдача в регистратор комнды "начать формирование документа на чеке"
		/// 2. Запоминание типа документа - чек
		/// </summary>
		/// <param name="DocType">тип документа</param>
		/// <param name="Copies">число копий</param>
		/// <param name="TableNo">номер столика, комнаты, ТРК</param>
		/// <param name="PlaceNo">номер места</param>
		/// <param name="AccountNo">номер счета</param>
		/// <example><code>StartReceipt(0, 1, "", "", "")</code></example>
		/// <returns>код ошибки</returns>
		public static int FRStartReceipt(byte docType, byte copies, string tableNo, string placeNo, string accountNo)
		{
			int i = StartReceipt(docType, copies, tableNo, placeNo, accountNo);
			str += "StartReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор команды "продажа на чеке"
		/// </summary>
		/// <param name="WareName">наименование товара / услуги</param>
		/// <param name="WareCode">артикул товара / код товара</param>
		/// <param name="Measure">еденицы измерения</param>
		/// <param name="SecID">наименование секции</param>
		/// <param name="Price">цена за штуку в копеках</param>
		/// <param name="Count">колличество в штуках / вес в миллиграммах</param>
		/// <param name="WareType">тип товара</param>
		/// <example><code>ItemReceipt("СИГАРЕТЫ SALEM", "012345", "ШТ", "БАКАЛЕЯ", 4950, 2000, 1)</code></example>
		/// <returns>код ошибки</returns>
		public static int FRItemReceipt(string wareName, string wareCode, string measure, string secID, int price, int count, byte wareType)
		{
			int i = ItemReceipt(
				GetOEMDOSStr(wareName), 
				GetOEMDOSStr(wareCode), 
				GetOEMDOSStr(measure), 
				GetOEMDOSStr(secID), 
				price, count, wareType
			);
			str += "ItemReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор командв "подитог на чеке"
		/// </summary>
		/// <returns>код ошибки</returns>
		public static int FRSubTotalReceipt()
		{
			int i = SubTotalReceipt();
			str += "SubTotalReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор команды "расчет на чеке"
		/// </summary>
		/// <param name="PayType">Вид оплаты</param>
		/// <param name="TenderSum">сумма в копейках, внесенная покупателем</param>
		/// <param name="CardName">название платежной карты</param>
		/// <example><code>TenderReceipt(0, 9900, "")</code></example>
		/// <returns>код ошибки</returns>
		public static int FRTenderReceipt(byte payType, int tenderSum, string cardName)
		{
			int i = TenderReceipt(payType, tenderSum, cardName);
			str += "TenderReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// <para>Выдача в регистратор команды "расчет на чеке"</para>
		/// <para>Печать произвольного текста на чеке</para>
		/// </summary>
		/// <param name="payType">Вид оплаты</param>
		/// <param name="tenderSum">сумма в копейках, внесенная покупателем</param>
		/// <param name="cardName">название платежной карты</param>
		/// <param name="freeField">Произвольный текст</param> 
		/// <example><code>TenderReceiptPlus(0, 9900, "", "Произвольная строка1 | Произвольная строка 2")</code></example>
		/// <returns>код ошибки</returns>
		public static int FRTenderReceiptPlus(byte payType, int tenderSum, string cardName, string freeField)
		{
			int i = TenderReceiptPlus(
				payType, 
				tenderSum, 
				GetOEMDOSStr(cardName), 
				GetOEMDOSStr(freeField)
			);
			str += "TenderReceiptPlus " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Назначить налог
		/// </summary>
		/// <param name="TaxType">Индекс налога</param>
		/// <returns>Код ошибки</returns>
		public static int FRTaxReceipt(byte taxType)
		{
			int i = TaxReceipt(taxType);
			str += "TaxReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// 1. Выдача в регистратор команды "итог на чеке"
		/// 2. Завершение оформления документа
		/// </summary>
		/// <returns>код ошибки</returns>
		public static int FRTotalReceipt()
		{
			int i = TotalReceipt();
			str += "TotalReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор команды "закрытие документа"
		/// </summary>
		/// <returns>код ошибки</returns>
		public static int FRCloseReceipt()
		{
			int i = CloseReceipt();
			str += "CloseReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор команды "Аннулирование документа на чеке"
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static int FRCancelReceipt()
		{
			int i = CancelReceipt();
			str += "CancelReceipt " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Изменяет формат выводимых символов
		/// </summary>
		/// <param name="Font">Маска шрифта в соответствии с командой ESC
		/// 	<para>  0 - Выбор шрифта (A или B)</para>
		/// 	<para>  1-2 - не определено</para>
		/// 	<para>  3 - жирность</para>
		/// 	<para>  4 - печатать символы удвоенной высоты</para>
		/// 	<para>  5 - печатать символы удвоенной ширины</para>
		/// 	<para>  6 - не определено</para>
		/// 	<para>  7 - символы с подчеркиванием</para>
		/// </param>
		/// <returns>Код ошибки</returns>
		/// <example>
		/// 	<code>
		/// 		<para>OpenFDoc();</para>
		/// 		<para>FontSelectFDoc(0x21);</para>
		/// 		<para>PrintOEMCRLFFDoc("Двойной ширины");</para>
		/// 		<para>FontSelectFDoc(0x11);</para>
		/// 		<para>PrintOEMCRLFFDoc("Двойной высоты");</para>
		/// 		<para>FontSelectFDoc(0x01);</para>
		/// 		<para>PrintOEMCRLFFDoc("Нормальный");</para>
		/// 		<para>CloseFDoc();</para>
		/// 	</code>
		/// </example>
		public static void FRFontSelectFDoc(byte font)
		{
			FontSelectFDoc(font);
		}
		
		/// <summary>
		/// Выдача в регистратор команды "открытие денежного ящика"
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static void FRCashDriverOpen()
		{
			CashDriverOpen();
		}
		
		/// <summary>
		/// Установить параметры денежного ящика
		/// </summary>
		/// <param name="OnTime">Время On в импульсах х 10ms</param>
		/// <param name="OffTime">Время Off в импульсах х 10ms</param>
		/// <example><code>  FRSetDrawerParam(5, 5) - установить на 50ms включение и 50ms выключение</code></example>
		/// <returns>Код ошибки</returns>
		public static int FRSetDrawerPram(byte onTime, byte offTime)
		{
			int i = SetDrawerPram(onTime, offTime, 0);
			str += "SetDrawerPram " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор команды "Программирование параметров налоговой ставки"
		/// </summary>
		/// <param name="index">Индекс налоговой ставки</param>
		/// <param name="name">Название</param>
		/// <param name="val">Процент</param>
		/// <example><code>FRSetTaxes(0, "НДС", "18")</code></example>
		/// <returns>Код ошибки</returns>
		public static int FRSetTaxes(byte index, string name, string val)
		{
			int i = SetTaxes(
				index, 
				0, 
				GetOEMDOSStr(name),
				GetOEMDOSStr(val),
				GetOEMDOSStr("0")
			);
			str += "SetTaxes " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор команды "Чтение параметров налоговой ставки"
		/// </summary>
		/// <param name="index">Индекс налоговой ставки</param>
		/// <example><code>  GetTaxes(0)</code></example>
		/// <returns>Код ошибки</returns>
		public static int FRGetTaxes(byte index)
		{
			int i = GetTaxes(index);
			str += "GetTaxes " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Выдача в регистратор команды "внесение"
		/// </summary>
		/// <param name="ToCash">Сумма внесенная в кассу(копейки)</param>
		/// <example><code>  FRToCash(12311) - Внести 123 рубля 11 коп в кассу</code></example>
		/// <returns>Код ошибки</returns>
		public static int FRToCash(int sum)
		{
			int i = ToCash(sum);
			str += "ToCash " + i + "\n";
			return i;
		}
		
		public static int FRGetErrorMessage()
		{
			int i;
			string str1;
			i = GetErrorMessage(out str1);
			Console.WriteLine(str1);
			return i;
		}
		
		/// <summary>
		/// Отчет по закрытиям смен в диапазоне номеров смен
		/// </summary>
		/// <param name="ReportType">Тип отчета
		/// 	<para>  06 - Полный</para>
		/// 	<para>  07 - Краткий</para>
		/// </param>
		/// <param name="StartNo">Номер начальной смены</param>
		/// <param name="EndNo">Номер конечной смены</param>
		/// <example><code>  EKLShiftsNumReport(06, 123, 321) - Напечатать полный отчет с 123 закрытия по 321</code></example>
		/// <returns>Код ошибки</returns>
		public static int FREKLShiftsNumReport(int reportType, int startNo, int endNo)
		{
			int i;
			i = EKLShiftsNumReport(reportType, startNo, endNo);
			str += "EKLShiftsNumReport " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Печатает X-Отчет
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static int FRXReport()
		{
			int i;
			i = XReport();
			str += "XReport " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Печать контрольной ленты за смену
		/// </summary>
		/// <returns>Код ошибки</returns>
		public static int FREJPrint()
		{
			int i = EJPrint();
			str += "EJPrint " + i + "\n";
			return i;
		}
		
		/// <summary>
		/// Печать документов из СКЛ в заданном диапазоне номеров
		/// </summary>
		/// <param name="StartNum">Начальный номер</param>
		/// <param name="EndNum">Конечный номер</param>
		/// <example><code>  EJNoReport(1, 10)</code></example>
		/// <returns>Код ошибки</returns>
		public static int FREJNoReport(int startNum,int endNum)
		{
			int i = EJNoReport(startNum, endNum);
			str += "EJNoReport " + i + "\n";
			return i;
		}
		#endregion
		
		#region Методы для высокоуровневой работы с ФР
		#region Методы для офрмления предчека
		/// <summary>
		/// Подготовка таблицы с товарами и ценами для ФР
		/// </summary>
		/// <param name="dt">Таблицы с данными</param>
		private static void FRFDocPrepareDataTableBody(DataTable dt)
		{
			checkFreeDataTable = new DataTable();
			
			checkFreeDataTable.Columns.Add("TovName", typeof(string));
			checkFreeDataTable.Columns.Add("TovKol", typeof(decimal));
			checkFreeDataTable.Columns.Add("TovEdIzm", typeof(string));
			checkFreeDataTable.Columns.Add("TovSOne", typeof(decimal));
			checkFreeDataTable.Columns.Add("TovS", typeof(decimal));
			
			for (int rowi = 0; rowi < dt.Rows.Count; rowi++) {
					DataRow row = checkFreeDataTable.NewRow();
					row["TovName"] = dt.Rows[rowi]["TovName"].ToString();
					row["TovKol"] = dt.Rows[rowi]["TovKol"].ToString();
					row["TovEdIzm"] = dt.Rows[rowi]["TovEdIzm"].ToString();
					row["TovSOne"] = dt.Rows[rowi]["TovSOne"].ToString();
					row["TovS"] = dt.Rows[rowi]["TovS"].ToString();
					checkFreeDataTable.Rows.Add(row);
			}
		}
		
		/// <summary>
		/// Печать заголовка не фискального чека
		/// </summary>
		private static void FRFDocPrintCheckFreeHeader()
		{
			FROpenFDoc();
			FRPrintOEMCRLFDoc(" ****************************************", 41);
            FRPrintOEMCRLFDoc(" *            ИП Мамонтов Л.Ю.          *", 41);
			FRPrintOEMCRLFDoc(" *      Р.Н.10368 ул.Белградская 4'г'   *", 41);
            FRPrintOEMCRLFDoc(" *         Булочная-Кофейня 'СИТИ'      *", 41);
            FRPrintOEMCRLFDoc(" *               Ч Е К                  *", 41);
			FRPrintOEMCRLFDoc(" ****************************************", 41);
			FRPrintOEMCRLFDoc("                                         ", 41);	
		}
		
		/// <summary>
		/// Печать части  не фискального чека с товарами и ценами
		/// </summary>
		private static void FRFDocPrintCheckFreeBody()
		{
			DataTable dt = checkFreeDataTable;
			string text = "";
			string tovName;
			string tovS;
			string tmpText;
			string tovSOne;
			string tovKol;
			string tovEdIzm;
			int l = 36;
			
			for (int rowi = 0; rowi < dt.Rows.Count; rowi++) {
				tovName = dt.Rows[rowi]["TovName"].ToString();
				tovSOne = dt.Rows[rowi]["TovSOne"].ToString();
				tovKol =  dt.Rows[rowi]["TovKol"].ToString();
				tovEdIzm = dt.Rows[rowi]["TovEdIzm"].ToString();
				tovS = dt.Rows[rowi]["TovS"].ToString();
				text = tovName;
				
				if (text.Length > (l - tovS.Length)){
					string[] strArr = getArrayStr(text, l);	
					for (int i = 0; i < strArr.Length; i++) {
						if (strArr[i].Length >= l) {
							tmpText = "   " + strArr[i].PadRight(l, ' ') + "   ";
							FRPrintOEMCRLFDoc(tmpText, 41);
						} else {
							tmpText = "   " + strArr[i].PadRight(l, ' ') + "   ";
							FRPrintOEMCRLFDoc(tmpText, 41);
						}
					}
					tmpText = tovKol + tovEdIzm + "*" + tovSOne;
					tmpText = "   " + tmpText.PadRight((l - 4) - tovS.Length, '.') + tovS + " руб";
					FRPrintOEMCRLFDoc(tmpText, 41);
					FRPrintOEMCRLFDoc("                                         ", 41);
				} else {
					FRPrintOEMCRLFDoc("   " + text, 41);
                    tmpText = tovKol + tovEdIzm + "*" + tovSOne;
                    tmpText = "   " + tmpText.PadRight((l - 4) - tovS.Length, '.') + tovS + " руб";
					FRPrintOEMCRLFDoc(tmpText, 41);
					FRPrintOEMCRLFDoc("                                         ", 41);
				}
			};
			FRPrintOEMCRLFDoc("                                         ", 41);
		}
		
		/// <summary>
		/// Печать итогов  не фискального чека
		/// </summary>
		private static void FRFDocPrintCheckFreeFooter()
		{
			decimal sum;
			decimal kol;
			DataTable dt = checkFreeDataTable;
			
			kol = (decimal)dt.Compute("Sum(TovKol)", "");
			sum = (decimal)dt.Compute("Sum(TovS)", "");
			
			string text =string.Concat( "  Итого ", kol,"ШТ") ;
			
			text = text.PadRight(35 - sum.ToString().Length, '.') + sum.ToString() + " руб";
			FRPrintOEMCRLFDoc(text, 41);
			FRPrintOEMCRLFDoc("                                         ", 41);
			FRPrintOEMCRLFDoc("Вознаграждение оффицианта приветствуется ", 41);
			FRPrintOEMCRLFDoc("                                         ", 41);
		}
		
		/// <summary>
		/// Печать  не фискального чека
		/// </summary>
		/// <param name="dt">Таблица с полями "TovName"(Имя товара), "TovS"(Сумма товара)</param>
		public static void FRFDocPrintCheckFree(DataTable dt)
		{
			FRFDocPrepareDataTableBody(dt);
			FRFDocPrintCheckFreeHeader();
			FRFDocPrintCheckFreeBody();
			FRFDocPrintCheckFreeFooter();
			FRFreeDocCutPlus(30);
		}
		#endregion
		
		#region Методы для формирования и печать таблицы с данными
		/// <summary>
		/// Метод печатает заголовок для таблицы с данными
		/// </summary>
		/// <param name="header">Текст заголовка</param>
		private static void FRFDocPrintDataTableHeader(string header)
		{
			FROpenFDoc();
			int l;
			string[] sa = header.Split(';');
            string text;

            for (int i = 0; i < sa.Length; i++)
            {
                l = 20 - (sa[i].Length / 2);
                text = "                     ".Substring(0, l) + sa[i];
                FRPrintOEMCRLFDoc(text, 41);
            }
			
			FRPrintOEMCRLFDoc("   ", 3);
			FRPrintOEMCRLFDoc("   ", 3);
		}
		
		/// <summary>
		/// Печатает содержимое таблицы с данными
		/// </summary>
		/// <param name="dt">Таблица с данными вида {string, double}</param>
		private static void FRFDocPrintDataTableBody(DataTable dt)
		{
			string text1;
			string text2;
			string textAll;
			int l;
			
			for (int rowi = 0; rowi < dt.Rows.Count; rowi++) {
				text1 = dt.Rows[rowi][0].ToString();
				text2 = dt.Rows[rowi][1].ToString();
				l = 41 - text2.Length;
				
				if (text1.Length < (l - 1)){
					textAll = text1.PadRight(l, '.') + text2;
					FRPrintOEMCRLFDoc(textAll, 41);
				} else {
					textAll = text1.Substring(0, l - 1) + "." + text2;
					FRPrintOEMCRLFDoc(textAll, 41);
				}
			}
		}
		
		/// <summary>
		/// Печатает итоги таблицы с данными
		/// </summary>
		/// <param name="dt">Таблица с данными вида {string, double}</param>
		/// <param name="itog">Текст итога</param>
		private static void FRFDocPrintDataTableFooter(DataTable dt, string itog)
		{
			string text = "И того:";
			decimal sum;
			string nameCol = dt.Columns[1].ColumnName.ToString();
			
			sum = Convert.ToDecimal(dt.Compute("Sum(" + nameCol + ")", ""));
				
			text = text.PadRight(41 - sum.ToString().Length, '.') + sum.ToString();
			FRPrintOEMCRLFDoc(text, 41);
			FRPrintOEMCRLFDoc("   ", 3);

            int l;
            string[] sa = itog.Split(';');

            for (int i = 0; i < sa.Length; i++)
            {
                l = 20 - (sa[i].Length / 2);
                text = "                     ".Substring(0, l) + sa[i];
                FRPrintOEMCRLFDoc(text, 41);
            }
		}
		
		/// <summary>
		/// Печатает в нефискальном режиме таблицу с данными
		/// </summary>
		/// <param name="dt">Таблица с данными вида {string, double}</param>
		/// <param name="header">Текст заголовка</param>
		/// <param name="itog">Текст итога после итогов таблицы</param>
		public static void FRFDocPrintDataTable(DataTable dt, string header, string itog)
		{
			FRFDocPrintDataTableHeader(header);
			FRFDocPrintDataTableBody(dt);
			FRFDocPrintDataTableFooter(dt, itog);
			FRFreeDocCutPlus(30);
		}
		#endregion.
		
		#region Методы для формирования фискального чека
		private static void FRCheckPrepareDataTableBory(DataTable dt)
		{
			 
			checkDataTable = new DataTable();
			
			checkDataTable.Columns.Add("TovName", typeof(string));
			checkDataTable.Columns.Add("TovCod", typeof(string));
			checkDataTable.Columns.Add("TovEdIzm", typeof(string));
			checkDataTable.Columns.Add("TovKol", typeof(decimal));
			checkDataTable.Columns.Add("TovSOne", typeof(decimal));
			
			for (int rowi = 0; rowi < dt.Rows.Count; rowi++) {
					DataRow row = checkDataTable.NewRow();
					row["TovName"] = dt.Rows[rowi]["TovName"].ToString();
					row["TovCod"] = dt.Rows[rowi]["TovCod"].ToString();
					row["TovEdIzm"] = dt.Rows[rowi]["TovEdIzm"].ToString();
					row["TovKol"] = dt.Rows[rowi]["TovKol"];
					row["TovSOne"] = dt.Rows[rowi]["TovSOne"];
					checkDataTable.Rows.Add(row);
			}
		}
		
		/// <summary>
		/// Начать формировать чек
		/// </summary>
		private static void FRCheckPrintHeader()
		{
			FRStartReceipt(0, 1, "", "", ""); // Начало формирования чека;
		}
		
		/// <summary>
		/// Добавление в чек наименований из таблицы товаров для чека
		/// </summary>
		private static void FRCheckPrintBody()
		{
			DataTable dt = checkDataTable;

			string tovName;
			string tovKod;
			string tovEdIzm;
			decimal tovKol;
			decimal tovSOne;

			int kolForFR; // Количество для ФР
			int prOneInKopForFR; // Цена за единицу в копейках для ФР
			
			for (int rowi = 0; rowi < dt.Rows.Count; rowi++) {
				tovName = dt.Rows[rowi]["TovName"].ToString();
				tovKod = dt.Rows[rowi]["TovCod"].ToString();
				tovEdIzm = dt.Rows[rowi]["TovEdIzm"].ToString();
				tovKol = (decimal)dt.Rows[rowi]["TovKol"];
				tovSOne = (decimal)dt.Rows[rowi]["TovSOne"];
				
				kolForFR = Convert.ToInt32(tovKol * 1000);
				prOneInKopForFR = Convert.ToInt32(tovSOne * 100);
				
				FRItemReceipt(
					tovName, 
					tovKod, 
					tovEdIzm, 
					"", 
					prOneInKopForFR, 
					kolForFR, 
					1
				); // Добавление наименования в чек
			};
		}
		
		/// <summary>
		/// Печать итога и завершение чека
		/// </summary>
		/// <param name="moneyBuyer">деньги внесенные покупателем</param>
		/// <example><code> FRCheckPrintFooter(100.10)</code></example>
		private static void FRCheckPrintFooter(decimal moneyBuyer)
		{
			int moneyBuyerInKop = Convert.ToInt32(moneyBuyer * 100);
				
			FRTotalReceipt(); // Итог на чеке
			FRTenderReceiptPlus(0, moneyBuyerInKop, "", " | | "); // Расчет на чеке
			FRCloseReceipt(); // Закрыть чек
		}
		
		/// <summary>
		/// Внести и распечатать фискальный чек
		/// </summary>
		/// <param name="dt">Таблица с набором наименований для чека</param>
		/// <param name="moneyBuyer">Деньги внесенные покупателем</param>
		/// <example><code> FRCheckPrint(dt, 100.10)</code></example>
		public static void FRCheckPrint(DataTable dt, decimal moneyBuyer)
		{
			FRCheckPrepareDataTableBory(dt); // Подготовка таблицы с товарами для чека
			FRCheckPrintHeader(); // Начало чека
			FRCheckPrintBody(); // Содержимое чека
			FRCheckPrintFooter(moneyBuyer); // Итог и завершение чека
			FRCashDriverOpen(); // Открытие ящика
		}
		#endregion
		
		#region Методы для формирования и печати накладной с данными
		/// <summary>
		/// Печать заголовка для накладной
		/// </summary>
		/// <param name="header">Текст заголовка разделенный знаком ';' для переноса строк</param>
		private static void FRFDocPrintNaklHeader(string header)
		{
			int l;
			string[] sa = header.Split(';');
            string text;

            for (int i = 0; i < sa.Length; i++)
            {
                l = 20 - (sa[i].Length / 2);
                text = "                     ".Substring(0, l) + sa[i];
                FRPrintOEMCRLFDoc(text, 41);
            }
			
			FRPrintOEMCRLFDoc("   ", 3);
			FRPrintOEMCRLFDoc("   ", 3);
		}
		
		/// <summary>
		/// Печать данных из таблицы по накладно
		/// </summary>
		/// <param name="dt">Таблицы с данными вида tovName, pr, kol</param>
		private static void FRFDocPrintNaklBody(DataTable dt)
		{
			string tovName;
			string pr;
			string kol;
			string text;
			decimal snds;
			
			for (int rowi = 0; rowi < dt.Rows.Count; rowi++) {
				tovName = dt.Rows[rowi]["tovName"].ToString();
				pr = dt.Rows[rowi]["pr"].ToString();
				kol = dt.Rows[rowi]["kol"].ToString();
				
				if (tovName.Length <= 41) {
					FRPrintOEMCRLFDoc(tovName, 41);
				} else {
					tovName = tovName.Substring(0, 41);
					FRPrintOEMCRLFDoc(tovName, 41);
				}
				
				snds = Convert.ToDecimal(pr) * Convert.ToDecimal(kol);
				text = " " + kol + "ШТ" + " по " + pr + " руб";
				text = text + (snds + " руб.").ToString().PadLeft(41-text.Length, '.');
				FRPrintOEMCRLFDoc(text, 41);
				FRPrintOEMCRLFDoc("  ", 2);
			}
		}
		
		/// <summary>
		/// Печать итогов накладной
		/// </summary>
		/// <param name="dt">Таблицы с данными вида tovName, pr, kol</param>
		/// <param name="itog">Текст итога после итогов накладной</param>
		private static void FRFDocPrintNaklFooter(DataTable dt, string itog)
		{
			DataColumn totalColumn = new DataColumn();
			totalColumn.DataType = System.Type.GetType("System.Decimal");
			totalColumn.ColumnName = "snds";
			totalColumn.Expression = "kol * pr";
			dt.Columns.Add(totalColumn);

			decimal sumKol;
			decimal sumSnds;
			
			sumKol = Convert.ToDecimal(dt.Compute("Sum(kol)", ""));
			sumSnds = Convert.ToDecimal(dt.Compute("Sum(snds)", ""));
			
			string text = "И того:";
			FRPrintOEMCRLFDoc(text, 41);
			
			text = " " + sumKol + "шт. общая стоимость" ;
			text = text.PadRight(36 - sumSnds.ToString().Length, '.') + sumSnds.ToString() + " руб.";
			FRPrintOEMCRLFDoc(text, 41);
			FRPrintOEMCRLFDoc("   ", 3);

            int l;
            string[] sa = itog.Split(';');

            for (int i = 0; i < sa.Length; i++)
            {
                l = 20 - (sa[i].Length / 2);
                text = "                     ".Substring(0, l) + sa[i];
                FRPrintOEMCRLFDoc(text, 41);
            }
		}
		
		/// <summary>
		/// Печать накладной
		/// </summary>
		/// <param name="dt">Таблицы с данными вида tovName, pr, kol</param>
		/// <param name="header">Текст заголовка накладной разделенный символом ';' для деления на строки</param>
		/// <param name="itog">Текст итога после итогов накладной</param>
		public static void FRFDocPrintNakl(DataTable dt, string header, string itog)
		{
            FRStartSeans();
			FROpenFDoc();
			FRFDocPrintNaklHeader(header);
			FRFDocPrintNaklBody(dt);
			FRFDocPrintNaklFooter(dt, itog);
			FRFreeDocCutPlus(30);
		}
		#endregion.
		#endregion
		
		#region вспомогательные методы
			
		/// <summary>
		/// Возвращает набор байтов в кодировке OEM/DOS
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		private static byte[] GetOEMDOSStr(string str)
		{
			Encoding cp = Encoding.GetEncoding(866);
			Encoding unicode = Encoding.Unicode;
			
			byte[] unicodeBytes = unicode.GetBytes(str);
			byte[] cpBytes = Encoding.Convert(unicode, cp, unicodeBytes);
			
			return cpBytes;
		}
		
		/// <summary>
		/// Возвращает массив строк заданной длины из исходной
		/// </summary>
		/// <param name="text">Исходная строка</param>
		/// <param name="length">Длина строки</param>
		/// <returns></returns>
		private static string[] getArrayStr(string text, int length)
		{
			int textRowCount = text.Length / length;
			string[] strArr = new string[textRowCount + 1];
			int l = text.Length;
			for (int i = 0; i <= textRowCount; i++) {
				if (text.Length > (i + 1) * length) {
					strArr[i] = text.Substring(i * length, length);
				} else {
					strArr[i] = text.Substring(i * length);
				}
			}
			return strArr;
		}
		#endregion
		#endregion
	}
}